<?php

/**
 * Created by JetBrains PhpStorm.
 * User: nietao
 * Date: 13-10-30
 * Time: 下午8:26
 * To change this template use File | Settings | File Templates.
 */
namespace Forxx;

use Lavender\Core;
use Lavender\Exception;

class FileHelper
{
    const FILE_PATH = 'file';
    const IMG_PATH = 'img';
    const VOICE_PATH = 'voice';
    const VIDEO_PATH = 'video';

    const UPLOAD_FIELD_NAME = "upfile";

    public static function move_file($from,$to,$is_upload = true){
        if(!file_exists($from)){
            Core::log("image","图片[{$from}]不存在\n");
            return false;//图片不存在
        }
        if(file_exists($to)){
            Core::log("image","图片[{$to}]已存在\n");
            return false;//图片已存在
        }
        $dir =  dirname($to);
        self::create_folder($dir);
        if($is_upload){
            move_uploaded_file($from,$to);
        }
        else{
            rename($from,$to);
        }
        return true;
    }

    public static function get_image_type_from_mine_type($mine_type){
        $type = false;
        switch ($mine_type) {
            case "image/jpg":
            case "image/jpeg":
            case "image/pjpeg":
                $type = 'jpeg';
                break;
            case "image/gif":
                $type = 'gif';
                break;
            case "image/png":
                $type = 'png';
                break;
            case "image/webp":
                $type = 'webp';
                break;
        }
        return $type;
    }

    public static function get_image_type_from_const($type){
        $ret = false;
        if($type == IMAGETYPE_GIF){
            $ret = 'gif';
        }
        else if($type == IMAGETYPE_JPEG){
            $ret = 'jpeg';
        }
        elseif($type == IMAGETYPE_PNG){
            $ret = 'png';
        }
        elseif($type == IMAGETYPE_WBMP){
            $ret = 'webp';
        }
        return $ret;
    }

    /**
     * 图片加水印
     * @param $srcImg
     * @param $waterImg
     * @param int $position 位置 1:左上 2:右上 3:左下 4 右下 5:中间
     * @param int $opacity 水印透明度 0 完全不透明 100 相当于没有水印
     * @param null $savename
     * @return int|string
     */
    public static function img_water_mark($srcImg, $waterImg, $position = 4,$savename = null,$opacity = 75){
        $opacity = intval($opacity);
        if($opacity < 0 || $opacity > 100){
            Core::log("image","水印透明度[{$opacity}]不合法\n");
            return false;
        }
        $opacity = abs(100 - $opacity);
        if(!file_exists($srcImg)){
            Core::log("image","水印原始图片[{$srcImg}]不存在\n");
            return false;
        }
        if(!file_exists($waterImg)){
            Core::log("image","水印图片[{$waterImg}]不存在\n");
            return false;
        }
        $tmpname = tempnam("/tmp","water_image_");
        if(!is_null($savename))
        {
            if(file_exists($savename)){
                Core::log("image","水印图片[{$waterImg}]已存在\n");
                return false;
            }
            $dir = dirname($savename);
            if(!is_dir($dir)){
                self::create_folder($dir);
            };
            $tmpname = $savename;
        }
        else{
            $savename = $srcImg;
        }
        $srcinfo = @getimagesize($srcImg);
        if(!$srcinfo){
            Core::log("image","原始图片[{$srcImg}]不合法\n");
            return false;
        }
        $waterinfo = @getimagesize($waterImg);
        if(!$waterinfo){
            Core::log("image","水印图片[{$srcImg}]不合法\n");
            return false;
        }
        $posinfo = self::getPositionInfo($srcinfo[0],$srcinfo[1],$waterinfo[0],$waterinfo[1],$position);
        if(!$posinfo){
            Core::log("image","水印位置[{$position}]不支持或者原始图片太小\n");
            return false;
        }
        $srcType = self::get_image_type_from_const($srcinfo[2]);
        $waterType = self::get_image_type_from_const($waterinfo[2]);
        if(!($srcType && $waterType)){
            Core::log("image","原始图片格式或者水印图片格式不支持\n");
            return false;
        }
        $srcFunc = "imagecreatefrom{$srcType}";
        $waterFunc = "imagecreatefrom{$waterType}";
        $srcIm = $srcFunc($srcImg);
        $waterIm = $waterFunc($waterImg);
        imagecopymerge($srcIm, $waterIm, $posinfo[0], $posinfo[1], 0, 0, $waterinfo[0], $waterinfo[1], $opacity);
        imagedestroy($waterIm);
        $outFunc = "image{$srcType}";
        $outFunc($srcIm, $tmpname);
        if(!file_exists($tmpname)){
            imagedestroy($srcIm);
            return false;
        }
        if($tmpname != $savename){
            @unlink($savename);
            rename($tmpname,$savename);
        }
        return true;
    }

    /**
     * @param $bX
     * @param $bY
     * @param $fX
     * @param $fY
     * @param $pos 位置 1:左上 2:右上 3:左下 4 右下 5:中间
     */
    public static function getPositionInfo($bX,$bY,$fX,$fY,$pos){
        $x= 0;
        $y= 0;
        if($bX < $fX || $bY < $fY){
            return false;
        }
        switch ($pos) {
            case 1:
                $x=$y=0;
                break;
            case 2:
                $x=$bX - $fX;
                $y=0;
                break;

            case 3:
                $x = 0;
                $y = $bY - $fY;
                break;
            case 4:
                $x = $bX - $fX;
                $y = $bY - $fY;
                break;
            case 5:
                $x= intval(floor(($bX - $fX)/2));
                $y= intval(floor(($bY - $fY)/2));
                break;
            default:
                return false;
        }
        return [$x,$y];
    }

    /**
     * 缩放图片
     * @param $from
     * @param $to
     * @param int $scale 比例尺
     */
    public static function resize_image($from,$to,$scale = 1,$autosubfix = true){
        if($scale <= 0 || $scale > 10){
            Core::log("image","缩放比例[{$scale}]不合法\n");
            return false;//图片不存在
        }
        if(!file_exists($from)){
            Core::log("image","图片[{$from}]不存在\n");
            return false;//图片不存在
        } 
        $dir =  dirname($to);
        self::create_folder($dir);
        $imageInfo = @getimagesize($from);
        if(!$imageInfo){
            //不是有效的图片
            Core::log("image","[{$from}]不是有效的图片\n");
            return false;
        }
        $inputX = $imageInfo[0];
        $inputY = $imageInfo[1];
        $type = self::get_image_type_from_const($imageInfo[2]);
        if(!$type){
            //图片格式不支持
            Core::log("image","[{$from}]图片格式不支持\n");
            return false;
        }
        $toX = intval($inputX * $scale);
        $toY = intval($inputY * $scale);
        $func = "imagecreatefrom{$type}";
        $originIm = $func($from);
        if (function_exists("imagecopyresampled")) {
            $newim = imagecreatetruecolor($toX, $toY);
            imagecopyresampled($newim, $originIm, 0, 0, 0, 0, $toX, $toY, $inputX, $inputY);
        } else {
            $newim = imagecreate($toX, $toY);
            imagecopyresized($newim, $originIm, 0, 0, 0, 0, $toX, $toY, $inputX, $inputY);
        }
        imagedestroy($originIm);
        if($autosubfix){
            $to = $to .".".$type;
        }
        $saveName = tempnam("/tpm", "resize_image_");
        $outFunc = "image{$type}";
        $outFunc($newim, $saveName);
        if(!file_exists($saveName)){
            Core::log("image","缩放图片失败\n");
            return false;//图片已存在
        }
        if(file_exists($to)){
            @unlink($to);
        }
        rename($saveName,$to);
        return [
            'file'=>$to,
            'type'=>$type,
            'size'=>filesize($to),
            'mtime'=>filemtime($to),
        ];
    }

    public static function upload_image($filename){
        $base_path = Core::get_config("const","file")['FILE_SAVE_PATH'];
        $hash = md5_file($filename);
        $cat = self::getRootPathByFileType("jpg");
        $path = "/{$cat}/".date("Ymd")."/";
        $tofile = $base_path.$path.$hash;
        self::move_file($filename,$tofile);
        return self::resize_image($tofile,$tofile);
    }

    /**
     * 下载远程文件
     * @param $url
     * @param $file_type
     * @param bool $compress 是否压缩
     * @return bool|string
     * @throws \Lavender\Exception
     */
    public static function download_remote_file($url,$file_type,$compress = true){
        $tmpname = tempnam("/tpm", "download_remote_");
        @file_put_contents($tmpname,@file_get_contents($url));
        $base_path = Core::get_config("const","file")['FILE_SAVE_PATH'];
        if(file_exists($tmpname)){
            $hash = md5_file($tmpname);
            $cat = self::getRootPathByFileType($file_type);
            $path = "/{$cat}/".substr($hash,0,2)."/".substr($hash,2,2)."/";
            $file = $path . $hash. ".".$file_type;
            $full = $base_path .$file;
            if(file_exists($full)){//图片已存在
                @unlink($tmpname);
                return $file;
            }
            else{
                $dir = dirname($full);
                self::create_folder($dir);
                rename($tmpname,$full);
            }
            //如果是图片 则尝试压缩
            if($cat == self::IMG_PATH && $compress){
                $ret = self::resize_image($full,$base_path.$path.$hash);
                if(!$ret){
                    @unlink($full);
                    Core::log("image","给出的url下载结果不是图片");
                    return false;
                }
                else{
                    $realname = $path.basename($ret['file']);
                    if($realname != $file){
                        @unlink($full);
                        $file = $realname;
                    }
                }
            }
            return $file;
        }
        Core::log("image","下载远程文件失败!");
        return false;
    }

    public static function getRootPathByFileType($file_type){
        $images = ['image','img','jpg','jpeg','png','gif','webp'];
        $sounds = ['mp3','aac'];
        $videos = ['mp4','mkv','avi'];
        $file_type = strtolower($file_type);
        $file_type = trim($file_type,'.');
        if(array_search($file_type,$images) !== false){
            return self::IMG_PATH;
        }
        if(array_search($file_type,$sounds) !== false){
            return self::VOICE_PATH;
        }
        if(array_search($file_type,$videos) !== false){
            return self::VIDEO_PATH;
        }
        return self::FILE_PATH;
    }

    public static function convertUrlPath2FilePath($path){
        return str_replace("/",DIRECTORY_SEPARATOR,$path);
    }

    /**
     * 逐级创建目录
     *
     * @param $path 路径
     * @param $mode 权限
     */
    public static function create_folder($path,$mode=0777)
    {
        if (!is_dir($path)) {
            mkdir($path, $mode,true);
        }
    }

    /**
     * 图片截取
     * @param $path
     */
    public static function imageCut($path,$savePath,$x,$y,$width,$height){
        $base_path = Core::get_config("const","file")['FILE_SAVE_PATH'];
        $realPath = "";
        if(file_exists($path)){
            $realPath = $path;

        }else{
            $realPath = $base_path . $path;
        }
        if(!file_exists($realPath)){
            throw new Exception("图片文件不存在或者已删除");
        }
        $imInfo = getimagesize($realPath);
        $originWidth = $imInfo[0];//原图宽度
        $originHeight = $imInfo[1];//原图宽度
        $imgType = $imInfo[2];//图片类型 1 为 GIF 格式、 2 为 JPEG/JPG 格式、3 为 PNG 格式
        if($imgType != 2 && $imgType != 3){
            throw new Exception("图片类型不支持剪裁!");
        }
        if( ($x+$width) > $originWidth || ($y+$height) > $originHeight) {
            throw new Exception("图片的剪裁尺寸超过限制!");
        }
        if($imgType == 2){
            $srcIm = @imagecreatefromjpeg($realPath);//读取原图像
        }else if($imgType == 3){
            $srcIm = @imagecreatefrompng($realPath);//读取原图像
        }
        $im = imagecreatetruecolor($width, $height);//创建真彩画布
        imagecopy($im,$srcIm,0,0,$x,$y,$width,$height);
        //保存到文件
        self::create_folder(dirname($savePath));
        if($imgType == 2) {
            imagejpeg($im, $savePath);
        }else if($imgType == 3){
            imagepng($im,$savePath);
        }
        imagedestroy($srcIm);
        imagedestroy($im);
        return $savePath;
    }

}